//
//  QuadNode.m
//  CompGraf2
//
//  Created by Juan Niosi on 24/10/11.
//  Copyright 2011 __MyCompanyName__. All rights reserved.
//

#import "QuadNode.h"

@implementation QuadNode
@synthesize level;

- (id)init:(int)lvl:(Bounds *)bnds
{
    self = [super init];
    if (self) {
        level = lvl;
        self.bounds = bnds;
        
        if (level > 0)
        {
            float halfX = [self.bounds getWidth] / 2.0f;
            float halfZ = [self.bounds getDepth] / 2.0f;
            int subLvl = level-1;
            
            Bounds *sub = [[Bounds alloc] initWithValues:bounds.xMin :bounds.xMax-halfX :bounds.yMin :bounds.yMax :bounds.zMin :bounds.zMax-halfZ];
            QuadNode *node = [[QuadNode alloc] init:subLvl :sub];
            [self addChild:node];
            
            sub = [[Bounds alloc] initWithValues:bounds.xMin+halfX :bounds.xMax :bounds.yMin :bounds.yMax :bounds.zMin :bounds.zMax-halfZ];
            node = [[QuadNode alloc] init:subLvl :sub];
            [self addChild:node];
            
            sub = [[Bounds alloc] initWithValues:bounds.xMin+halfX :bounds.xMax :bounds.yMin :bounds.yMax :bounds.zMin+halfZ :bounds.zMax];
            node = [[QuadNode alloc] init:subLvl :sub];
            [self addChild:node];
            
            sub = [[Bounds alloc] initWithValues:bounds.xMin :bounds.xMax-halfX :bounds.yMin :bounds.yMax :bounds.zMin+halfZ :bounds.zMax];
            node = [[QuadNode alloc] init:subLvl :sub];
            [self addChild:node];
        }
        else
        {
            [self.children addObject:[[Entity alloc] init]];
            [self.children addObject:[[Entity alloc] init]];
        }
    }
    
    return self;
}

- (BOOL)addEntity:(Entity *)ent atIndex:(int)idx
{
    if (idx == 0) //floor
    {
        if (ent.bounds.xMin < self.bounds.xMin || ent.bounds.xMax > self.bounds.xMax
            || ent.bounds.zMin < self.bounds.zMin || ent.bounds.zMax > self.bounds.zMax)
        {
            return false;
        }
    }
    else //wall
    {
        float epsilon = 0.2f; //Wall width
        if (ent.bounds.xMin < self.bounds.xMin-epsilon || ent.bounds.xMax > self.bounds.xMax+epsilon
            || ent.bounds.zMin < self.bounds.zMin-epsilon || ent.bounds.zMax > self.bounds.zMax+epsilon)
        {
            return false;
        }
    }
    
    if (level == 0)
    {   
        Entity *child = [children objectAtIndex:idx];
        [child addChild:ent];
        return true;
    }
    else
    {
        for (QuadNode *qn in children)
        {
            if ([qn addEntity:ent atIndex:idx])
                return true;
        }
        NSLog(@"Error de QuadTree: No pertenece a esta hoja");
        return false;
    }
}

- (void)optimize
{
    if (level > 0)
    {
        for (QuadNode *qn in children)
            [qn optimize];
    }
    else
    {
        if ([children count] == 0)
            return;
        
        for (Entity *child in children)
        {
            if ([child.children count] == 0)
                continue;
            
            Entity *opt = [child.children objectAtIndex:0];
            [child.children removeObjectAtIndex:0];
            for (int i = 1; i < [child.children count]; i++)
            {
                [opt merge:[child.children objectAtIndex:0]];
                [child.children removeObjectAtIndex:0];
            }
            [child addChild:opt];
        }
    }
}

- (void)draw:(Engine *)engine:(Camera *)cam
{
    if (level > 0 || [cam isVisible:bounds])
    {
        //[bounds draw:engine];
        
        if (level > 0)
        {
            for (QuadNode *child in children)
                [child draw:engine :cam];
        }
        else
        {
            for (Entity *child in children)
                [child draw:engine :cam];
        }
        
    }
    else
    {
        //NSLog(@"NOT VISIBLE: %@", name);
    }
}

- (void)dealloc
{
    [super dealloc];
}
@end
